package com.qf.factory;

import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

/**
 * @Description: 公用常量
 * @Data: 2022/8/26 11:10
 * @Pacakge: com.qf.factory
 * @ClassName: BeanFactory
 * @Author: fan
 * 工厂类
 * 作用:用来获取对应的bean,通过加载配置文件读取配置信息,再用反射的方式初始化对象
 */
public class BeanFactory {
    private static Properties properties;

   /* 多例--->单例
    只需要保证adminDao是同一个
    工厂类加载的时候,就应该将对应的配置文件加载,生成实例
    也就是说在静态代码块里就要完场bean的初始化
    生成的bean实例就要存储起来--->通过集合存储
    通过Map集合进行优化
    */
    private static Map<String,Object> beans;
    static{
        try {
            //获取输入流
            InputStream is
                    = BeanFactory.class.getClassLoader().getResourceAsStream("bean.properties");
            //创建对应的properties对象
            properties = new Properties();
            //加载输入流
            properties.load(is);

            //修改:多例-->单例
            //初始化map
            beans = new HashMap<String,Object>();
            //properties本身就是一个map,(k:v,k1:v1)
            // ("adminDao":"com.qf.dao.impl.AdminDaoImpl","adminService":"com.qf.service.impl.AdminServiceImpl")
            //获取properties中所有的key
            Enumeration<Object> keys = properties.keys();
            //循环去获取指定key的value值
            while(keys.hasMoreElements()){//判断key中有没有下一个元素的值
                //获得key
                String key = keys.nextElement().toString();
                //通过key获取value
                String value = properties.getProperty(key);//value的值就是全路径类名,如:com.qf.dao.impl.AdminDaoImpl
                //通过反射获取对象的实例
                Object o = Class.forName(value).newInstance();
                //将对应的bean存储到容器中
                beans.put(key,o);

            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    //定义一个功能获取bean实例的方法
    public static Object getBean(String name){
        //通过key值获取value
        String value = properties.getProperty(name);
        //通过反射获取实例对象
        //多例,每次调用会重复生成新的对象,虽然解决了解耦,但是在性能方面没有得到优化
        try {
            Object o = Class.forName(value).newInstance();
            return o;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 通过单例模式获取实体类对象
     * @param name 实体类的名称
     * @return 实体类
     */
    public static Object getBeansByOne(String name){
         return beans.get(name);
    }


}
